/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.push.application.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.foreveross.bsl.common.utils.mapper.BeanMapper;
import com.foreveross.bsl.push.application.CheckinEvent;
import com.foreveross.bsl.push.application.CheckinService;
import com.foreveross.bsl.push.application.PushModuleException;
import com.foreveross.bsl.push.application.UpdateTagEvent;
import com.foreveross.bsl.push.application.vo.DeviceCheckinVo;
import com.foreveross.bsl.push.application.vo.TagEntryVo;
import com.foreveross.bsl.push.domain.entity.DeviceCheckin;
import com.foreveross.bsl.push.domain.entity.TagEntry;
import com.foreveross.bsl.push.repository.DeviceCheckinRepository;

/**
 * 默认的签到服务实现：设备保持第三方长连接服务器后，签到到此服务，把需要的信息保存
 * 
 * @author Wangyi
 * @version v1.0
 *
 * @date 2013-7-8
 *
 */
@Named("defaultCheckinService")
public class DefaultCheckinService implements CheckinService {
	
	private final static Logger log = LoggerFactory.getLogger(DefaultCheckinService.class);
	
	@Inject
	private EventPostHelper eventPostHelper;

	private final DeviceCheckinRepository getDeviceCheckinRepository() {
		return new DeviceCheckin().getEntityRepository(DeviceCheckinRepository.class);
	}
	
	@Override
	public void checkin(DeviceCheckinVo vo) {
		Assert.notNull(vo);
		Assert.notNull(vo.getAppId());
		if(StringUtils.isBlank(vo.getPushToken()) || "null".equals(vo.getPushToken())) // apns token, 当证书吊销时，获取的值为"null", android 这个值存的是instant返回的token
			return;
		DeviceCheckin po = this.getDeviceCheckinRepository().findByDeviceIdAndAppId(vo.getDeviceId(), vo.getAppId());
		if (po == null) {
			po = BeanMapper.map(vo, DeviceCheckin.class);
			po.setId(null);
			po.setCreateTime(new Date());
		} else {
			// BeanMapper.copy(vo, po); TODO 是否有忽略"null"的属性
			po.setAlias(vo.getAlias());
			po.setAppId(vo.getAppId());
			po.setChannelId(vo.getChannelId()); // ios: apns  android:instant
			po.setDeviceId(vo.getDeviceId());
			po.setDeviceName(vo.getDeviceName());
			po.setGis(vo.getGis());
			po.setOsName(vo.getOsName());
			po.setOsVersion(vo.getOsVersion());
			po.setPushToken(vo.getPushToken()); // ios pushToken, 当证书吊销时，获取的值为"null"
			if(vo.getTags() != null) { // 更新标签
				List<TagEntry> tags=BeanMapper.mapList(Arrays.asList(vo.getTags()), TagEntry.class);
				po.setTags(po.getTagsHelper().updateTags(tags).getTags());
			}
		}
		po.setOnline(true);
		po.setCheckinTime(new Date());
		this.getDeviceCheckinRepository().save(po);

		BeanMapper.copy(po, vo);
		if(po.getTags()!=null){
			TagEntryVo[] tagVos=new TagEntryVo[po.getTags().size()];
			int i=0;
			for(TagEntry te : po.getTags()){
				tagVos[i++]=BeanMapper.map(te, TagEntryVo.class);
			}
			vo.setTags(tagVos);
		}
		log.info("签到已更新, deviceId:{}, appId:{}, channelId:{},token:{},tag:{}", po.getDeviceId(), 
				po.getAppId(), po.getChannelId(), po.getPushToken(), po.getTagsHelper().getTags());
		this.eventPostHelper.post(new CheckinEvent(CheckinEvent.Action.Checkin, vo)); // 发送离线信息
		log.info("签到事件已触发");
	}
	
	@Override
	public void updateTags(String deviceId, String appId, Map<String, String> tags, String alias) {
		Assert.notNull(deviceId);
		Assert.notNull(appId);
		
		DeviceCheckin po = this.getDeviceCheckinRepository().findByDeviceIdAndAppId(deviceId, appId);
		if(po == null) {
			throw new PushModuleException("不存在设备签到信息，deviceId："+deviceId+", appId："+appId);
		}
		if(tags!=null) {
			po.setTags(po.getTagsHelper().updateTags(tags).getTags());
		} else {
			po.setTags(null);
		}
		po.setAlias(alias);
		
		this.getDeviceCheckinRepository().save(po);
		this.eventPostHelper.post(new UpdateTagEvent(deviceId, appId, tags));
		log.info("标签更新事件已触发");
	}

}
